package com.yricky.memoria.ui.component

import android.graphics.Bitmap
import androidx.compose.material.ScaffoldState
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.yricky.memoria.data.*
import com.yricky.memoria.utils.Executor
import com.yricky.memoria.utils.PdfDoc
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.io.InputStream

/**
 * @author Yricky
 * @date 2021/11/21
 */
class MainActivityContentViewModel:ViewModel() {


    fun setWorkSpaceModel(ws: WorkSpaceModel){
        workSpaceModel.value = ws
    }
    private val workSpaceModel:MutableLiveData<WorkSpaceModel> by lazy {
        MutableLiveData<WorkSpaceModel>().also {
            it.observeForever { querySubList() }
        }
    }
    private val ws:WorkSpaceModel? get() = workSpaceModel.value
    val focusedSubject:MutableLiveData<SubjectModel> by lazy {
        MutableLiveData<SubjectModel>().also {
            it.observeForever {
                queryFocusedSubject()
            }
        }
    }


    data class ViewState(
        val subjectList:List<Pair<String,List<WorkSpaceModel.SubjectMetaData>>> = emptyList(),
        val tagFoldStat:Map<String,Boolean> = emptyMap(),
        val fSubjectMetaData:WorkSpaceModel.SubjectMetaData? = null,
        val fSubjectSectionList:List<SubjectModel.SectionMetaData> = emptyList(),
        val fSubjectTags: List<String> = emptyList(),
        val fSubjectPdf:List<Pair<String,PdfDoc>> = emptyList()
    )
    private val _viewState: MutableStateFlow<ViewState> = MutableStateFlow(ViewState())
    val viewState = _viewState.asStateFlow()


    sealed class Action{
        object QuerySubjects:Action()
        object QuerySections:Action()
        class AddSubject(val name:String):Action()
        class ToggleTagFold(val name:String,val stat:Boolean):Action()
        class DeletePdf(val name:String):Action()
    }

    fun onAction(action:Action){
        when(action){
            is Action.QuerySubjects -> querySubList()
            is Action.QuerySections -> queryFocusedSubject()
            is Action.AddSubject -> addSubject(action.name)
            is Action.ToggleTagFold -> {
                _viewState.value = _viewState.value.copy(
                    tagFoldStat = _viewState.value.tagFoldStat.toMutableMap().also {
                        it[action.name] = action.stat
                    }
                )
            }
            is Action.DeletePdf -> {
                focusedSubject.value?.let { subject ->
                    subject.pdfDir(action.name).deleteRecursively()
                    queryPdf()
                }
            }
        }
    }

    fun setFocusedSubject(metaData: WorkSpaceModel.SubjectMetaData){
        focusedSubject.value = workSpaceModel.value?.openSubject(metaData)
    }



    lateinit var scaffoldState: ScaffoldState
    lateinit var scope: CoroutineScope

    // 在Drawer侧栏显示指定的标签分组
    fun highLightTag(tagName:String){
        openDrawer()
        _viewState.value = _viewState.value.copy(
            tagFoldStat = _viewState.value.tagFoldStat.let { map->
                HashMap<String,Boolean>().also{ newMap ->
                    map.forEach{
                        newMap[it.key] = false
                    }
                    newMap[tagName] = true
                }
            }
        )
    }
    // 在Drawer侧栏展示当前笔记所在的标签分组
    fun highLightCurrentSubject(){
        focusedSubject.value?.uid?.let {
            highLightSubject(it)
        }
    }
    // 在Drawer侧栏展示指定笔记所在的标签分组
    fun highLightSubject(subjectUid:String){
        openDrawer()
        ws?.tagManager?.getMyTags(subjectUid)?.also { list ->
            _viewState.value = _viewState.value.copy(
                tagFoldStat = _viewState.value.tagFoldStat.let { map ->
                    HashMap<String, Boolean>().also { newMap ->
                        map.forEach {
                            newMap[it.key] = false
                        }
                       list.forEach {
                            newMap[it] = true
                        }
                        if(list.isEmpty()){
                            // 若指定笔记无标签，显示”全部“笔记列表
                            newMap[""] = true
                        }
                    }
                }
            )
        }
    }
    // 打开Drawer侧栏
    fun openDrawer(){
        if(this::scaffoldState.isInitialized && this::scope.isInitialized){
            scope.launch {
                scaffoldState.drawerState.apply {
                    if (isClosed) open() else close()
                }
            }
        }
    }
    // 关闭Drawer侧栏
    fun closeDrawer(){
        if(this::scaffoldState.isInitialized && this::scope.isInitialized){
            scope.launch {
                scaffoldState.drawerState.apply {
                    if (isOpen) close() else open()
                }
            }
        }
    }


    private fun addSubject(name:String){
        Executor.exec{
            ws?.addSubject(name)
            querySubList()
        }
    }

    fun delSubject(metaData: WorkSpaceModel.SubjectMetaData){
        Executor.exec{
            ws?.delSubject(metaData)
            ws?.tagManager?.unlinkMyTags(metaData.uid)
            querySubList()
        }
    }

    fun modSubject(metaDataOld: WorkSpaceModel.SubjectMetaData, metaDataNew: WorkSpaceModel.SubjectMetaData){
        Executor.exec{
            ws?.modSubject(metaDataOld, metaDataNew)
            querySubList()
            if(_viewState.value.fSubjectMetaData == metaDataOld){
                _viewState.value = _viewState.value.copy(
                    fSubjectMetaData = metaDataNew
                )
            }
        }
    }


    fun delSection(metaData: SubjectModel.SectionMetaData){
        Executor.exec{
            focusedSubject.value?.delSection(metaData)
            // 删除标签关联
            queryFocusedSubject()
        }
    }

    fun modSection(metaDataOld: SubjectModel.SectionMetaData, metaDataNew: SubjectModel.SectionMetaData){
        Executor.exec{
            focusedSubject.value?.modSection(metaDataOld, metaDataNew)
            queryFocusedSubject()
        }
    }

    private fun querySubList(){
        Executor.exec{
            val list = mutableListOf(Pair("",ws?.getSubjects()?: emptyList()))
            val tags:List<String> = ws?.tagManager?.getTags() ?: emptyList()
            val tagFoldStat:MutableMap<String,Boolean> = _viewState.value.tagFoldStat.toMutableMap()
            if(tagFoldStat[""] == null){
                tagFoldStat[""] = false
            }
            tags.forEach { tagName ->
                tagFoldStat[tagName] = true
                list.add(Pair(tagName, ws?.getSubjectsByTag(tagName)?: emptyList()))
            }
            viewModelScope.launch {
                _viewState.value = _viewState.value.copy(
                    tagFoldStat = tagFoldStat,
                    subjectList = list
                )

            }
        }
    }

    private fun queryFocusedSubject(){
        Executor.exec{
            val list = focusedSubject.value?.getSections() ?: emptyList()
            viewModelScope.launch {
                _viewState.value = _viewState.value.copy(
                    fSubjectMetaData = focusedSubject.value?.metaData,
                    fSubjectSectionList = list
                )
                queryPdf()
            }
        }
    }

    private fun queryPdf(){
        viewModelScope.launch {
            val metaData = _viewState.value.fSubjectMetaData
            val list = withContext(Dispatchers.IO) {
                focusedSubject.value?.pdfList() ?: emptyList()
            }
            if(metaData == _viewState.value.fSubjectMetaData)
                _viewState.value = _viewState.value.copy(fSubjectPdf = list)
        }
    }

    fun addTag2Subject(tagName: String, subjectUID: String) {
        Executor.exec{
            ws?.tagManager?.linkTag(tagName, subjectUID)
            querySubList()
        }
    }
    fun unlinkTagFromSubject(subject: WorkSpaceModel.SubjectMetaData, belongedTag: String) {
        Executor.exec{
            ws?.tagManager?.unlinkTag(belongedTag, subject.uid)
            querySubList()
        }
    }
    private fun getTagsOfSubject(subject: WorkSpaceModel.SubjectMetaData):List<String> {
        return ws?.tagManager?.getMyTags(subject.uid) ?: emptyList()
    }
    fun getTagsOfFocusedSubject(): List<String> {
        return focusedSubject.value?.let { getTagsOfSubject(it.metaData) } ?: listOf()
    }

    fun importPdf(name:String,inS:InputStream){
        viewModelScope.launch {
            withContext(Dispatchers.IO){
                focusedSubject.value?.importPdf(name, inS)
                queryPdf()
            }
        }
    }


    fun addTag2Section(tagName: String, uid: String) {
        // TODO: 给Section添加标签
    }


    fun renameTag(tagNameOld: String, tagNameNew: String) {
        Executor.exec{
            ws?.tagManager?.modTag(tagNameOld, tagNameNew)
            querySubList()
        }
    }
    fun delTag(tagName: String){
        Executor.exec{
            ws?.tagManager?.delTag(tagName)
            querySubList()
        }
    }


}